const fs = require('fs').promises
const path = require('path')
const { v4: uuidv4 } = require('uuid')
const config = require('../config')
const logger = require('../utils/logger')
const { ERROR_CODES } = require('../utils/constants')

class BaseModel {
  constructor(tableName) {
    this.tableName = tableName
    this.dbPath = path.resolve(config.database.path)
    this.data = null
    this.lastModified = null
  }

  /**
   * 读取数据库文件
   */
  async loadData() {
    try {
      const stats = await fs.stat(this.dbPath)
      
      // 如果文件没有修改，使用缓存数据
      if (this.data && this.lastModified && stats.mtime <= this.lastModified) {
        return this.data
      }

      const fileContent = await fs.readFile(this.dbPath, 'utf8')
      this.data = JSON.parse(fileContent)
      this.lastModified = stats.mtime
      
      return this.data
    } catch (error) {
      logger.error('Failed to load database', error, { dbPath: this.dbPath })
      throw new Error(`${ERROR_CODES.DATABASE_ERROR}: 无法读取数据库文件`)
    }
  }

  /**
   * 保存数据到文件
   */
  async saveData(data) {
    try {
      const jsonString = JSON.stringify(data, null, 2)
      await fs.writeFile(this.dbPath, jsonString, 'utf8')
      
      this.data = data
      this.lastModified = new Date()
      
      logger.debug('Database saved successfully', { tableName: this.tableName })
    } catch (error) {
      logger.error('Failed to save database', error, { dbPath: this.dbPath })
      throw new Error(`${ERROR_CODES.DATABASE_ERROR}: 无法保存数据库文件`)
    }
  }

  /**
   * 获取表数据
   */
  async getTable() {
    const data = await this.loadData()
    return data[this.tableName] || []
  }

  /**
   * 更新表数据
   */
  async updateTable(tableData) {
    const data = await this.loadData()
    data[this.tableName] = tableData
    await this.saveData(data)
  }

  /**
   * 查找所有记录
   */
  async findAll(filter = {}) {
    const table = await this.getTable()
    
    if (Object.keys(filter).length === 0) {
      return table
    }

    return table.filter(item => {
      return Object.keys(filter).every(key => {
        if (typeof filter[key] === 'object' && filter[key] !== null) {
          // 支持复杂查询条件
          return this.matchCondition(item[key], filter[key])
        }
        return item[key] === filter[key]
      })
    })
  }

  /**
   * 根据ID查找记录
   */
  async findById(id) {
    const table = await this.getTable()
    return table.find(item => item.id === id) || null
  }

  /**
   * 查找单个记录
   */
  async findOne(filter) {
    const results = await this.findAll(filter)
    return results.length > 0 ? results[0] : null
  }

  /**
   * 创建新记录
   */
  async create(data) {
    const table = await this.getTable()
    
    const newRecord = {
      id: uuidv4(),
      ...data,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    }

    table.push(newRecord)
    await this.updateTable(table)
    
    logger.debug('Record created', { tableName: this.tableName, id: newRecord.id })
    return newRecord
  }

  /**
   * 更新记录
   */
  async update(id, updateData) {
    const table = await this.getTable()
    const index = table.findIndex(item => item.id === id)
    
    if (index === -1) {
      return null
    }

    const updatedRecord = {
      ...table[index],
      ...updateData,
      updatedAt: new Date().toISOString()
    }

    table[index] = updatedRecord
    await this.updateTable(table)
    
    logger.debug('Record updated', { tableName: this.tableName, id })
    return updatedRecord
  }

  /**
   * 删除记录
   */
  async delete(id) {
    const table = await this.getTable()
    const index = table.findIndex(item => item.id === id)
    
    if (index === -1) {
      return false
    }

    const deletedRecord = table[index]
    table.splice(index, 1)
    await this.updateTable(table)
    
    logger.debug('Record deleted', { tableName: this.tableName, id })
    return deletedRecord
  }

  /**
   * 批量删除
   */
  async deleteMany(filter) {
    const table = await this.getTable()
    const toDelete = table.filter(item => {
      return Object.keys(filter).every(key => item[key] === filter[key])
    })

    if (toDelete.length === 0) {
      return 0
    }

    const remainingTable = table.filter(item => {
      return !Object.keys(filter).every(key => item[key] === filter[key])
    })

    await this.updateTable(remainingTable)
    
    logger.debug('Records deleted', { tableName: this.tableName, count: toDelete.length })
    return toDelete.length
  }

  /**
   * 计数
   */
  async count(filter = {}) {
    const results = await this.findAll(filter)
    return results.length
  }

  /**
   * 分页查询
   */
  async paginate(filter = {}, options = {}) {
    const { page = 1, limit = 10, sort = {} } = options
    const offset = (page - 1) * limit

    let results = await this.findAll(filter)
    const total = results.length

    // 排序
    if (Object.keys(sort).length > 0) {
      results = this.sortResults(results, sort)
    }

    // 分页
    const paginatedResults = results.slice(offset, offset + limit)

    return {
      data: paginatedResults,
      pagination: {
        page,
        limit,
        total,
        pages: Math.ceil(total / limit)
      }
    }
  }

  /**
   * 匹配查询条件
   */
  matchCondition(value, condition) {
    if (condition.$eq !== undefined) return value === condition.$eq
    if (condition.$ne !== undefined) return value !== condition.$ne
    if (condition.$gt !== undefined) return value > condition.$gt
    if (condition.$gte !== undefined) return value >= condition.$gte
    if (condition.$lt !== undefined) return value < condition.$lt
    if (condition.$lte !== undefined) return value <= condition.$lte
    if (condition.$in !== undefined) return condition.$in.includes(value)
    if (condition.$nin !== undefined) return !condition.$nin.includes(value)
    if (condition.$regex !== undefined) {
      const regex = new RegExp(condition.$regex, condition.$options || '')
      return regex.test(value)
    }
    return false
  }

  /**
   * 排序结果
   */
  sortResults(results, sort) {
    return results.sort((a, b) => {
      for (const [field, direction] of Object.entries(sort)) {
        const aVal = a[field]
        const bVal = b[field]
        
        if (aVal < bVal) return direction === 1 ? -1 : 1
        if (aVal > bVal) return direction === 1 ? 1 : -1
      }
      return 0
    })
  }

  /**
   * 事务支持（简单实现）
   */
  async transaction(operations) {
    const originalData = await this.loadData()
    
    try {
      const results = []
      for (const operation of operations) {
        const result = await operation()
        results.push(result)
      }
      return results
    } catch (error) {
      // 回滚
      await this.saveData(originalData)
      throw error
    }
  }
}

module.exports = BaseModel